import { Injectable } from '@nestjs/common';
import { cmdExec, getBundle, getDataPath } from '../utils';
import { appListCmd } from './cmd';
import { Socket } from 'net';
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
import { join } from 'path';

const getCacheFromFile = (SN: string) => {
  const dataPath = getDataPath();
  if (dataPath && SN) {
    const SNPath = join(dataPath, SN);
    if (existsSync(SNPath)) {
      const cacheFile = join(SNPath, 'app_list');
      if (existsSync(cacheFile)) {
        return readFileSync(cacheFile).toString();
      }
    }
  }
  return '';
};

const setCacheToFile = (SN: string, data: string) => {
  try {
    const dataPath = getDataPath();
    if (dataPath && SN) {
      const SNPath = join(dataPath, SN);
      if (!existsSync(SNPath)) {
        mkdirSync(SNPath);
      }
      const cacheFile = join(SNPath, 'app_list');
      writeFileSync(cacheFile, data);
    }
  } catch (err) {
    console.log('app_list缓存文件写入失败');
  }
};

const getAppListBySocket = (SN: string, bundle: string) => {
  return new Promise<string>(async (resolve, reject) => {
    try {
      const cache = getCacheFromFile(SN);
      if (cache) return cache;
      let appList = '';
      await cmdExec(appListCmd.hdc.startApp(SN, bundle));
      await cmdExec('hdc fport tcp:12347 tcp:4567');
      const client = new Socket();
      client.on('data', (data) => {
        appList += data;
        const last = data.toString().slice(-3);
        if (last === '$$$') {
          appList = appList.toString().slice(0, -3);
          setCacheToFile(SN, appList);
          resolve(appList);
        }
      });
      setTimeout(() => {
        client.connect(12347, '127.0.0.1', () => {
          client.write('get_app_list');
        });
      }, 500);
      client.on('error', (err) => {
        console.log('getAppListBySocket connect error: ', err);
        resolve('');
      });
    } catch (err) {
      console.log('getAppListBySocket error: ', err);
      reject('');
    }
  });
};

const cacheAppList = new Map<string, any[]>();

@Injectable()
export class AppListService {
  async getAppList(SN: string) {
    if (cacheAppList.has(SN)) return cacheAppList.get(SN);
    const bundle = await getBundle(SN);
    const ret = await getAppListBySocket(SN, bundle);
    try {
      const appList = JSON.parse(ret) || [];
      if (SN && appList.length) {
        cacheAppList.set(SN, [...appList]);
      }
      return appList;
    } catch (err) {
      console.log('get app list error: ', err);
    }
  }
  clearAppList(SN: string) {
    cacheAppList.delete(SN);
  }
}
